﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace CSharpChapters_3
{
    class LambdaExample
    {
        public static void LambdaPrint()
        {
            LambdaExp.ExpPrint();

            //捕获变量的 lambda 表达式
            var demo = new CapturedVariablesDemo();
            Action<string> action = demo.CreateAction("method argument");
            action("lambad argument");

            //局部变量的多次实例化
            //为每次初始化创建上下文实例
            List<Action> actions = demo.CreateActions();
            foreach (var item in actions)
            {
                item();
            }

            List<Action> actions_1 = demo.CreateCountingActions();
            actions_1[0]();
            actions_1[0]();
            actions_1[1]();
            actions_1[1]();


            //手动创建表达式树——两个整型值相加
            ParameterExpression xParameter = Expression.Parameter(typeof(int), "x");
            ParameterExpression yParameter = Expression.Parameter(typeof(int), "y");
            Expression body = Expression.Add(xParameter, yParameter);
            ParameterExpression[] parameters = new[] { xParameter, yParameter };
            Expression<Func<int, int, int>> adder = Expression.Lambda<Func<int, int, int>>(body, parameters);
            Console.WriteLine(adder);
            //把表达式树编译成委托，并调用委托得到结果
            Expression<Func<int, int, int>> adder_1 = (x, y) => x + y;
            Func<int, int, int> executableAdder = adder.Compile();//该方法返回一个委托类型
            Console.WriteLine(executableAdder(2, 3));
        }
    }
    #region Lambda表达式
    public class LambdaExp
    {
        public static void ExpPrint()
        {
            //lambda表达式:内联代码简化委托

            //exp_1: 无返回值
            Action<string> action = delegate (string message)
            {
                Console.WriteLine("Message:{0}", message);
            };

            Action<string> action_1 = (string message) =>
            {
                Console.WriteLine("Message:{0}", message);
            };

            Action<string> action_2 = (string message) => Console.WriteLine("Message:{0}", message);

            //Action<string> action_3 = (message) => Console.WriteLine("Message:{0}", message);
            Action<string> action_3 = message => Console.WriteLine("Message:{0}", message);


            action("delegate");
            action_1("delegate_1");
            action_1("delegate_2");
            action_1("delegate_3");

            //exp_2：有返回值
            Func<int, int, int> multiply = (int x, int y) => { return x * y; };

            Func<int, int, int> multiply_1 = (x, y) => x * y;

            Console.WriteLine("multiply:{0}", multiply(10, 10));
            Console.WriteLine("multiply:{0}", multiply_1(11, 11));

            //exp_3
            Func<string, int> squareLength = (string text) =>
            {
                int length = text.Length;
                return length * length;
            };

            Func<string, int> squareLength_1 = text => text.Length * text.Length;

            Console.WriteLine("SquareLength:{0}", squareLength_1("145145"));

        }
    }
    #endregion

    #region lambda表达式捕获变量
    class CapturedVariablesDemo
    {
        private string instanceField = "insatance field";

        public Action<string> CreateAction(string methodParameter)
        {
            string methodLocal = "method local";
            string uncaptured = "uncaptured local";

            Action<string> action = lambdaParameter =>
            {
                string lambdaLocal = "lambda local";
                Console.WriteLine("Instance field:{0}", instanceField);
                Console.WriteLine("Method parameter:{0}", methodParameter);
                Console.WriteLine("Method local:{0}", methodLocal);
                Console.WriteLine("lambda parameter:{0}", lambdaParameter);
                Console.WriteLine("lambda local:{0}", lambdaLocal);
            };
            methodLocal = "modified method local";
            return action;
        }

        public List<Action> CreateActions()
        {
            List<Action> actions = new List<Action>();
            for (int i = 0; i < 5; i++)
            {
                LambdaContext context = new LambdaContext();
                context.text = string.Format("Message {0}", i);
                actions.Add(() => context.Method());
            }
            return actions;
        }

        #region 从多个作用域捕获变量
        public List<Action> CreateCountingActions()
        {
            List<Action> actions = new List<Action>();
            int outerCounter = 0;
            for (int i = 0; i < 2; i++)
            {
                int innerCounter = 0;
                Action action = () =>
                {
                    Console.WriteLine("Outer: {0}; Inner: {1}", outerCounter, innerCounter);
                    outerCounter++;
                    innerCounter++;
                };
                actions.Add(action);
            }
            return actions;
        }
        #endregion

    }

    class LambdaContext
    {
        public string text;
        public void Method()
        {
            Console.WriteLine(text);
        }
    }
    #endregion

    
}
